/*
 * Eugen Stoian <stoian.e@gmail.com> 2010
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "OpIFNode.h"
#include "ValueNode.h"
#include "OperandsException.h"
#include <cmath>
static Real opIF(const Real& left, const Real& right) {
    if(right.isTrue()){
        return left;
    }
    return Real::nan();
}

static SmartPtr<ExpressionTreeNode> opIFDerivativeBuilder(SmartPtr<ExpressionTreeNode> node, const QString& varName) {
    if(!node)
        return 0;
    if(node->info()!=IF_SYMBOL)
        return 0;
    if(!node->right())
        return 0;
    if(!node->left())
        return 0;
    SmartPtr<ExpressionTreeNode> root = 0;
    SmartPtr<ExpressionTreeNode> left = 0;
    SmartPtr<ExpressionTreeNode> right = 0;

    left = node->left()->derive(varName);
    if(!left)
        return 0;
    right = node->right()->derive(varName);

    if(!right){
        return 0;
    }
    QString branchPath;
    if(right->isValue() && (right->eval().isFalse())){
        return new ValueNode(Real::nan());
    }

    root = new OpIFNode();
    root->setLeft(left);
    root->setRight(right);

    SmartPtr<ExpressionTreeNode> tmp = root->simplified();
    return tmp;
}

OpIFNode::OpIFNode():BinaryOpNode(IF_SYMBOL, &opIF, &opIFDerivativeBuilder){
}

ExpressionTreeNode* OpIFNode::copy() const {
    SmartPtr<ExpressionTreeNode> left = 0;
    SmartPtr<ExpressionTreeNode> right = 0;
    ExpressionTreeNode *root = 0;
    if(_left)
        left = _left->copy();
    if(_right)
        right = _right->copy();
    root = new OpIFNode();
    root->setLeft(left);
    root->setRight(right);
    return root;
}

int OpIFNode::precedence() const {
    return IF_PRECEDENCE;
}

SmartPtr<ExpressionTreeNode> OpIFNode::firstLevelSimplification() const {
    SmartPtr<ExpressionTreeNode> root = 0;
    if(!_left || !_right)
        return 0;
    SmartPtr<ExpressionTreeNode> left = _left->firstLevelSimplification();
    if(!left)
        return 0;
    SmartPtr<ExpressionTreeNode> right = _right->firstLevelSimplification();
    if(!right){
        return 0;
    }
    QString branchPath;
    if(right->isValue()){
        if(right->eval().isTrue()){
            return left;
        }
        if(right->eval().isFalse()){
            return new ValueNode(Real::nan());
        }
    }
    root = new OpIFNode();
    root->setLeft(left);
    root->setRight(right);
    return root;
}

void OpIFNode::setLeft(SmartPtr<ExpressionTreeNode> node)  throw (OperandsException){
    _left = node;
}

void OpIFNode::setRight(SmartPtr<ExpressionTreeNode> node)  throw (OperandsException){
    _right = node;

}
